/* eslint-disable no-console */

import crypto from "crypto";
import fs from "fs";
import http from "http";
import https from "https";
import path from "path";
import { fileURLToPath } from "url";
import zlib from "zlib";

import * as tar from "tar";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const BRANDING_INFO_FILE = path.join(__dirname, "../.branding");
const BRANDING_DIR = path.join(__dirname, "../branding");
const INSTALLED_BRANDING_INFO_FILE = path.join(BRANDING_DIR, ".branding");
const TEMP_FILE = path.join(__dirname, "branding_download.tar.gz");

function downloadFile(url, dest) {
	return new Promise((resolve, reject) => {
		const file = fs.createWriteStream(dest);
		const protocol = url.startsWith("https") ? https : http;

		const request = protocol.get(url, (response) => {
			if (response.statusCode === 301 || response.statusCode === 302 || response.statusCode === 307) {
				file.close();
				fs.unlink(dest, () => {});
				if (response.headers.location) {
					downloadFile(response.headers.location, dest).then(resolve).catch(reject);
				} else {
					reject(new Error("Redirect location missing"));
				}
				return;
			}

			if (response.statusCode !== 200) {
				file.close();
				fs.unlink(dest, () => {});
				reject(new Error(`Failed to download: ${response.statusCode}`));
				return;
			}

			response.pipe(file);
			file.on("finish", () => {
				file.close(resolve);
			});
		});

		request.on("error", (err) => {
			fs.unlink(dest, () => {});
			reject(err);
		});
	});
}

async function main() {
	if (!fs.existsSync(BRANDING_INFO_FILE)) {
		console.error(`Branding info file not found at ${BRANDING_INFO_FILE}`);
		process.exit(1);
	}

	const content = fs.readFileSync(BRANDING_INFO_FILE, "utf8");

	if (fs.existsSync(INSTALLED_BRANDING_INFO_FILE)) {
		const installedContent = fs.readFileSync(INSTALLED_BRANDING_INFO_FILE, "utf8");
		if (content === installedContent) {
			console.log("Branding assets are up to date.");
			return;
		}
	}

	const lines = content
		.split("\n")
		.map((l) => l.trim())
		.filter((l) => l.length > 0);

	if (lines.length < 2) {
		console.error("Branding file must contain at least two lines: URL and Hash");
		process.exit(1);
	}

	const url = lines[0];
	const expectedHash = lines[1];

	console.log(`Downloading branding assets from ${url}...`);

	try {
		await downloadFile(url, TEMP_FILE);
	} catch (err) {
		console.error("Download failed:", err);
		process.exit(1);
	}

	console.log("Download complete. Verifying hash...");

	const fileBuffer = fs.readFileSync(TEMP_FILE);
	const hashSum = crypto.createHash("sha256");
	hashSum.update(fileBuffer);
	const hex = hashSum.digest("hex");

	if (hex !== expectedHash) {
		console.error("Hash mismatch!");
		console.error(`Expected: ${expectedHash}`);
		console.error(`Actual:   ${hex}`);
		if (fs.existsSync(TEMP_FILE)) fs.unlinkSync(TEMP_FILE);
		process.exit(1);
	}

	console.log("Hash verified. Extracting...");

	if (fs.existsSync(BRANDING_DIR)) {
		fs.rmSync(BRANDING_DIR, { recursive: true, force: true });
	}
	fs.mkdirSync(BRANDING_DIR, { recursive: true });

	try {
		// Extract the tar.gz file
		await new Promise((resolve, reject) => {
			fs.createReadStream(TEMP_FILE)
				.pipe(zlib.createGunzip())
				.pipe(
					tar.x({
						cwd: BRANDING_DIR,
						strip: 1,
					}),
				)
				.on("error", reject)
				.on("finish", resolve);
		});
		fs.copyFileSync(BRANDING_INFO_FILE, INSTALLED_BRANDING_INFO_FILE);
		console.log("Extraction complete.");
	} catch (error) {
		console.error("Failed to extract archive:", error);
	} finally {
		if (fs.existsSync(TEMP_FILE)) {
			fs.unlinkSync(TEMP_FILE);
		}
	}
}

main()
	.then(() => process.exit(0))
	.catch((err) => {
		console.error("An error occurred:", err);
		process.exit(1);
	});
